﻿using System;
using System.Drawing;
using System.Media;
using System.Windows.Forms;
using npomodoro.Core;

namespace UI
{
    public partial class Main : Form
    {
        private const string DEFAULT_NOTIFY_ICON_MESSAGE = "No Active Pomodoro";
        private const string START_POMDORO_MENU_TEXT = "Start New Pomdoro";
        private const string STOP_POMDORO_MENU_TEXT = "Stop Current Pomodoro";
        private const string POMODORO_COMPLETED_MESSAGE = "The current Pomodoro has completed.";
        private const string REST_PERIOD_COMPLETED_MESSAGE = "The current rest period has completed.";

        private const int SHORT_REST_PERIOD_IN_SECONDS = 300;
        private const int LONG_REST_PERIOD_IN_SECONDS = 1200;

        private const string CANNOT_START_REST_PERIOD_WHILE_IN_POMDORO_MESSAGE =
            "Cannot start a rest period while a Pomodoro is active.  Please stop the current Pomdoro first.";

        private const string START_SHORT_REST_PERIOD_MESSAGE = "Start Short Rest Period";
        private const string START_LONG_REST_PERIOD_MESSAGE = "Start Long Rest Period";

        private Pomodoro m_CurrentPomdoro;
        private RestPeriod m_CurrentRestPeriod;
        private readonly SoundPlayer m_SoundPlayer;

        public Main()
        {
            InitializeComponent();

            ConfigureNotifyIcon();
            ConfigureMenus();

            InitializeEvents();

            startOrStopPomodoroMenuItem.Text = START_POMDORO_MENU_TEXT;

            m_SoundPlayer = new SoundPlayer(@"C:\Windows\Media\chimes.wav");

            HideApplication();
        }

        private void ConfigureMenus()
        {
            startShortRestPeriodMenuItem.Text = START_SHORT_REST_PERIOD_MESSAGE;
            startLongRestPeriodMenuItem.Text = START_LONG_REST_PERIOD_MESSAGE;
        }

        private void PlayNotification()
        {
            m_SoundPlayer.Play();
        }

        private void ConfigureNotifyIcon()
        {
            notifyIcon.Icon = Icon.FromHandle(((Bitmap) iconImages.Images[0]).GetHicon());
            notifyIcon.Text = DEFAULT_NOTIFY_ICON_MESSAGE;
        }

        private void InitializeEvents()
        {
            notifyIcon.MouseClick += OnNotifyMouseClick;
            monitorPomdoroTimer.Tick += OnMonitorPomodoroTimerClick;

            closeApplicationMenuItem.Click += delegate { Application.Exit(); };
            startOrStopPomodoroMenuItem.Click += OnStartOrStopPomodoroClick;
            startShortRestPeriodMenuItem.Click += OnStartShortRestPeriodClick;
            startLongRestPeriodMenuItem.Click += OnStartLongRestPeriodClick;
        }

        private void OnStartShortRestPeriodClick(object sender, EventArgs e)
        {
            if (CurrentlyActiveRestPeriod() && CurrentRestPeriodIsLong())
            {
                EndCurrentRestPeriod();
                StartLongRestPeriod();
                return;
            }

            if (CurrentlyActiveRestPeriod() && CurrentRestPeriodIsShort())
            {
                EndCurrentRestPeriod();
                return;
            }

            StartShortRestPeriod();
        }

        private bool CurrentRestPeriodIsShort()
        {
            return m_CurrentRestPeriod.TotalRunTime.Seconds == SHORT_REST_PERIOD_IN_SECONDS;
        }

        private bool CurrentRestPeriodIsLong()
        {
            return m_CurrentRestPeriod.TotalRunTime.Seconds == LONG_REST_PERIOD_IN_SECONDS;
        }

        private void StartShortRestPeriod()
        {
            m_CurrentRestPeriod = new RestPeriod(SHORT_REST_PERIOD_IN_SECONDS);
            m_CurrentRestPeriod.Start();

            startShortRestPeriodMenuItem.Text = "End Short Rest Period";

            StartRestPeriod();
        }

        private void OnStartLongRestPeriodClick(object sender, EventArgs e)
        {
            if (CurrentlyActiveRestPeriod() && CurrentRestPeriodIsLong())
            {
                EndCurrentRestPeriod();
                return;
            }

            if (CurrentlyActiveRestPeriod() && CurrentRestPeriodIsShort())
            {
                EndCurrentRestPeriod();
                StartShortRestPeriod();
                return;
            }

            StartLongRestPeriod();
        }

        private void StartLongRestPeriod()
        {
            m_CurrentRestPeriod = new RestPeriod(LONG_REST_PERIOD_IN_SECONDS);
            m_CurrentRestPeriod.Start();

            startLongRestPeriodMenuItem.Text = "End Long Rest Period";

            StartRestPeriod();
        }

        private void StartRestPeriod()
        {
            if (CurrentlyActivePomodoro())
            {
                notifyIcon.ShowBalloonTip(1000, "Unable to Start Rest Period",
                                          CANNOT_START_REST_PERIOD_WHILE_IN_POMDORO_MESSAGE,
                                          ToolTipIcon.Error);
                return;
            }

            notifyIcon.ShowBalloonTip(2000, "Starting Rest Period",
                                      string.Format("Starting a new rest period which will last {0} minutes",
                                                    m_CurrentRestPeriod.TotalRunTime.Minutes),
                                      ToolTipIcon.None);

            monitorPomdoroTimer.Enabled = true;
            UpdateNotifyIconText(m_CurrentRestPeriod);
        }

        private void OnMonitorPomodoroTimerClick(object sender, EventArgs e)
        {
            if (CurrentlyActivePomodoro())
            {
                UpdatePomodoro();
            }
            else if (CurrentlyActiveRestPeriod())
            {
                UpdateRestPeriod();
            }
            else
            {
                DisableNotifyIconTimer();
                return;
            }
        }

        private void UpdateRestPeriod()
        {
            if (m_CurrentRestPeriod.IsFinished())
            {
                notifyIcon.ShowBalloonTip(10000, "Rest Period Completed", REST_PERIOD_COMPLETED_MESSAGE,
                                          ToolTipIcon.Info);

                EndCurrentRestPeriod();
            }
            else
            {
                UpdateNotifyIconText(m_CurrentRestPeriod);
            }
        }

        private void UpdatePomodoro()
        {
            if (m_CurrentPomdoro.IsFinished())
            {
                notifyIcon.ShowBalloonTip(10000, "Pomdoro Completed", POMODORO_COMPLETED_MESSAGE,
                                          ToolTipIcon.Info);

                EndCurrentPomodoro();
            }
            else
            {
                UpdateNotifyIconText(m_CurrentPomdoro);
            }
        }

        private bool CurrentlyActiveRestPeriod()
        {
            return m_CurrentRestPeriod != null;
        }

        private void UpdateNotifyIconText(TimedActivityBase activity)
        {
            if (activity.RemainingTime.Minutes > 0)
            {
                notifyIcon.Text = string.Format("Current {0} has {1} minutes remaining.",
                                                activity.Name,
                                                activity.RemainingTime.Minutes);
            }
            else
            {
                notifyIcon.Text = string.Format("Current {0} has less then one minute remaining.",
                                                activity.Name);
            }
        }

        private void UpdateStatusText(string message)
        {
            
        }

        private void DisableNotifyIconTimer()
        {
            notifyIcon.Text = DEFAULT_NOTIFY_ICON_MESSAGE;
            monitorPomdoroTimer.Enabled = false;
        }

        private void OnStartOrStopPomodoroClick(object sender, EventArgs e)
        {
            if (!CurrentlyActivePomodoro())
            {
                StartPomodoro();
            }
            else
            {
                EndPomodoro();
            }
        }

        private void EndPomodoro()
        {
            var endingPomodorMessage = GetEndingPomdoroMessage();

            notifyIcon.ShowBalloonTip(0, "Ending Pomodoro", endingPomodorMessage, ToolTipIcon.None);
            EndCurrentPomodoro();
        }

        private void StartPomodoro()
        {
            if (CurrentlyActiveRestPeriod())
            {
                EndCurrentRestPeriod();
            }

            notifyIcon.ShowBalloonTip(0, "Starting Pomodoro",
                                      "Starting a new Pomodor which will last 25 minutes.",
                                      ToolTipIcon.None);

            startOrStopPomodoroMenuItem.Text = STOP_POMDORO_MENU_TEXT;

            m_CurrentPomdoro = new Pomodoro();
            m_CurrentPomdoro.Start();

            DisableRestMenuItems();

            monitorPomdoroTimer.Enabled = true;
            UpdateNotifyIconText(m_CurrentPomdoro);
        }

        private void EndCurrentRestPeriod()
        {
            DisableNotifyIconTimer();
            m_CurrentRestPeriod = null;

            PlayNotification();

            startShortRestPeriodMenuItem.Text = START_SHORT_REST_PERIOD_MESSAGE;
            startLongRestPeriodMenuItem.Text = START_LONG_REST_PERIOD_MESSAGE;
        }

        private void DisableRestMenuItems()
        {
            startShortRestPeriodMenuItem.Enabled = false;
            startLongRestPeriodMenuItem.Enabled = false;
        }

        private void EndCurrentPomodoro()
        {
            startOrStopPomodoroMenuItem.Text = START_POMDORO_MENU_TEXT;

            DisableNotifyIconTimer();
            m_CurrentPomdoro = null;
            PlayNotification();
            EnableRestMenuItems();
        }

        private void EnableRestMenuItems()
        {
            startShortRestPeriodMenuItem.Enabled = true;
            startLongRestPeriodMenuItem.Enabled = true;
        }

        private bool CurrentlyActivePomodoro()
        {
            return m_CurrentPomdoro != null;
        }

        private string GetEndingPomdoroMessage()
        {
            return m_CurrentPomdoro.IsFinished()
                       ? "Pomodoro has been completed."
                       : "Pomdoro was cancelled before completion.";
        }

        private void OnNotifyMouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ChangeWindowState();
            }
        }

        private void ChangeWindowState()
        {
            if (WindowState == FormWindowState.Minimized)
            {
                ShowApplication();
            }
            else
            {
                HideApplication();
            }
        }

        private void ShowApplication()
        {
            FormBorderStyle = FormBorderStyle.FixedSingle;
            ShowInTaskbar = true;
            Show();
            WindowState = FormWindowState.Normal;
        }

        private void HideApplication()
        {
            FormBorderStyle = FormBorderStyle.None;
            ShowInTaskbar = false;
            Hide();
            WindowState = FormWindowState.Minimized;
        }
    }
}